package com.yingxue.lesson.aop.aspect;


import com.alibaba.fastjson.JSON;
import com.yingxue.lesson.aop.annotation.MyLog;
import com.yingxue.lesson.contants.Constant;
import com.yingxue.lesson.entity.SysLog;
import com.yingxue.lesson.mapper.SysLogMapper;
import com.yingxue.lesson.utils.HttpContextUtils;
import com.yingxue.lesson.utils.IPUtils;
import com.yingxue.lesson.utils.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.UUID;

@Aspect
@Component
@Slf4j
public class SysLogAspect {

    @Autowired
    private SysLogMapper sysLogMapper;
    @Autowired
    private HttpServletRequest request;


    //定义切点
    @Pointcut("@annotation(com.yingxue.lesson.aop.annotation.MyLog)")
    public void logPointCut(){}

    //环绕增强
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable{
        long startTime = System.currentTimeMillis();
        //执行目标方法
        Object result = point.proceed();
        //执行时长(毫秒)
        long time = System.currentTimeMillis()-startTime;
        //保存日志
        try {
            saveSysLog(point,time);
        } catch (Exception e) {
            log.error("e={}",e);
        }
        return result;
    }

    //插入日志
    public void saveSysLog(ProceedingJoinPoint point,long time){
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();

        SysLog sysLog = new SysLog();
        //获取自定义注解
        MyLog myLog = method.getAnnotation(MyLog.class);
        if (myLog !=null ){
            //注解描述
            sysLog.setOperation(myLog.title()+"-"+myLog.action());
        }
        //获取 请求类名，请求方法名
        String className = point.getTarget().getClass().getName();
        String methodName = signature.getName();

        sysLog.setMethod(className+"."+methodName+"()");
        //打印该方法耗时时间
        log.info("请求{}.{}耗时{}毫秒",className,methodName,time);
        try {
            //获取请求参数
            Object[] args = point.getArgs();
            String params = null;
            if (args.length !=0){
                 params = JSON.toJSONString(args);
            }
            sysLog.setParams(params);
        } catch (Exception e) {

        }
        //获取request
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        //设置IP地址
        sysLog.setIp(IPUtils.getIpAddr(request));
        log.info("Ip{}，接口地址{}，请求方式{}，入参：{}",sysLog.getIp(),request.getRequestURL(),request.getMethod(),sysLog.getParams());
        //或取token,用户名，userId
        String token = request.getHeader(Constant.ACCESS_TOKEN);
        String userId = JwtTokenUtil.getUserId(token);
        String username = JwtTokenUtil.getUserName(token);
        //封装
        sysLog.setUsername(username);
        sysLog.setUserId(userId);
        sysLog.setTime((int) time);
        sysLog.setId(UUID.randomUUID().toString());
        sysLog.setCreateTime(new Date());
        log.info(sysLog.toString());
        //插入日志
        sysLogMapper.insertSelective(sysLog);
    }


}
